home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 21 / Cream of the Crop 21 (Terry Blount) (October 1996).iso / os2 / e33el2.zip / emacs / 19.33 / lisp / solar.el < prev    next >
Lisp/Scheme  |  1996-05-23  |  45KB  |  1,046 lines

  1. ;;; solar.el --- calendar functions for solar events.
  2.  
  3. ;; Copyright (C) 1992, 1993, 1995 Free Software Foundation, Inc.
  4.  
  5. ;; Author: Edward M. Reingold <reingold@cs.uiuc.edu>
  6. ;;    Denis B. Roegel <Denis.Roegel@loria.fr>
  7. ;; Keywords: calendar
  8. ;; Human-Keywords: sunrise, sunset, equinox, solstice, calendar, diary,
  9. ;;    holidays
  10.  
  11. ;; This file is part of GNU Emacs.
  12.  
  13. ;; GNU Emacs is free software; you can redistribute it and/or modify
  14. ;; it under the terms of the GNU General Public License as published by
  15. ;; the Free Software Foundation; either version 2, or (at your option)
  16. ;; any later version.
  17.  
  18. ;; GNU Emacs is distributed in the hope that it will be useful,
  19. ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  20. ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  21. ;; GNU General Public License for more details.
  22.  
  23. ;; You should have received a copy of the GNU General Public License
  24. ;; along with GNU Emacs; see the file COPYING.  If not, write to the
  25. ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  26. ;; Boston, MA 02111-1307, USA.
  27.  
  28. ;;; Commentary:
  29.  
  30. ;; This collection of functions implements the features of calendar.el,
  31. ;; diary.el, and holiday.el that deal with times of day, sunrise/sunset, and
  32. ;; equinoxes/solstices.
  33.  
  34. ;; Based on the ``Almanac for Computers 1984,'' prepared by the Nautical
  35. ;; Almanac Office, United States Naval Observatory, Washington, 1984, on
  36. ;; ``Astronomical Formulae for Calculators,'' 3rd ed., by Jean Meeus,
  37. ;; Willmann-Bell, Inc., 1985, on ``Astronomical Algorithms'' by Jean Meeus,
  38. ;; Willmann-Bell, Inc., 1991, and on ``Planetary Programs and Tables from
  39. ;; -4000 to +2800'' by Pierre Bretagnon and Jean-Louis Simon, Willmann-Bell,
  40. ;; Inc., 1986.
  41.  
  42. ;;
  43. ;; Accuracy:
  44. ;;    1. Sunrise/sunset times will be accurate to the minute for years
  45. ;;       1951--2050.  For other years the times will be within +/- 2 minutes.
  46. ;;
  47. ;;    2. Equinox/solstice times will be accurate to the minute for years
  48. ;;       1951--2050.  For other years the times will be within +/- 1 minute.
  49.  
  50. ;; Comments, corrections, and improvements should be sent to
  51. ;;  Edward M. Reingold               Department of Computer Science
  52. ;;  (217) 333-6733                   University of Illinois at Urbana-Champaign
  53. ;;  reingold@cs.uiuc.edu             1304 West Springfield Avenue
  54. ;;                                   Urbana, Illinois 61801
  55.  
  56. ;;; Code:
  57.  
  58. (if (fboundp 'atan)
  59.     (require 'lisp-float-type)
  60.   (error "Solar/lunar calculations impossible since floating point is unavailable."))
  61.  
  62. (require 'cal-dst)
  63. (require 'cal-julian)
  64.  
  65. ;;;###autoload
  66. (defvar calendar-time-display-form
  67.   '(12-hours ":" minutes am-pm
  68.     (if time-zone " (") time-zone (if time-zone ")"))
  69.   "*The pseudo-pattern that governs the way a time of day is formatted.
  70.  
  71. A pseudo-pattern is a list of expressions that can involve the keywords
  72. `12-hours', `24-hours', and `minutes',  all numbers in string form,
  73. and `am-pm' and `time-zone',  both alphabetic strings.
  74.  
  75. For example, the form
  76.  
  77.   '(24-hours \":\" minutes
  78.     (if time-zone \" (\") time-zone (if time-zone \")\"))
  79.  
  80. would give military-style times like `21:07 (UTC)'.")
  81.  
  82. ;;;###autoload
  83. (defvar calendar-latitude nil
  84.   "*Latitude of `calendar-location-name' in degrees.
  85.  
  86. The value can be either a decimal fraction (one place of accuracy is
  87. sufficient), + north, - south, such as 40.7 for New York City, or the value
  88. can be a vector [degrees minutes north/south] such as [40 50 north] for New
  89. York City.
  90.  
  91. This variable should be set in `site-start'.el.")
  92.  
  93. ;;;###autoload
  94. (defvar calendar-longitude nil
  95.   "*Longitude of `calendar-location-name' in degrees.
  96.  
  97. The value can be either a decimal fraction (one place of accuracy is
  98. sufficient), + east, - west, such as -73.9 for New York City, or the value
  99. can be a vector [degrees minutes east/west] such as [73 55 west] for New
  100. York City.
  101.  
  102. This variable should be set in `site-start'.el.")
  103.  
  104. (defsubst calendar-latitude ()
  105.   "Convert calendar-latitude to a signed decimal fraction, if needed."
  106.   (if (numberp calendar-latitude)
  107.       calendar-latitude
  108.     (let ((lat (+ (aref calendar-latitude 0)
  109.                   (/ (aref calendar-latitude 1) 60.0))))
  110.       (if (equal (aref calendar-latitude 2) 'north)
  111.           lat
  112.         (- lat)))))
  113.  
  114. (defsubst calendar-longitude ()
  115.   "Convert calendar-longitude to a signed decimal fraction, if needed."
  116.   (if (numberp calendar-longitude)
  117.       calendar-longitude
  118.     (let ((long (+ (aref calendar-longitude 0)
  119.                   (/ (aref calendar-longitude 1) 60.0))))
  120.       (if (equal (aref calendar-longitude 2) 'east)
  121.           long
  122.         (- long)))))
  123.  
  124. ;;;###autoload
  125. (defvar calendar-location-name
  126.   '(let ((float-output-format "%.1f"))
  127.      (format "%s%s, %s%s"
  128.              (if (numberp calendar-latitude)
  129.                  (abs calendar-latitude)
  130.                (+ (aref calendar-latitude 0)
  131.                   (/ (aref calendar-latitude 1) 60.0)))
  132.              (if (numberp calendar-latitude)
  133.                  (if (> calendar-latitude 0) "N" "S")
  134.                (if (equal (aref calendar-latitude 2) 'north) "N" "S"))
  135.              (if (numberp calendar-longitude)
  136.                  (abs calendar-longitude)
  137.                (+ (aref calendar-longitude 0)
  138.                   (/ (aref calendar-longitude 1) 60.0)))
  139.              (if (numberp calendar-longitude)
  140.                  (if (> calendar-longitude 0) "E" "W")
  141.                (if (equal (aref calendar-longitude 2) 'east) "E" "W"))))
  142.   "*Expression evaluating to name of `calendar-longitude', calendar-latitude'.
  143. For example, \"New York City\".  Default value is just the latitude, longitude
  144. pair.
  145.  
  146. This variable should be set in `site-start'.el.")
  147.  
  148. (defvar solar-error 0.5
  149. "*Tolerance (in minutes) for sunrise/sunset calculations.
  150.  
  151. A larger value makes the calculations for sunrise/sunset faster, but less
  152. accurate.  The default is half a minute (30 seconds), so that sunrise/sunset
  153. times will be correct to the minute.
  154.  
  155. It is useless to set the value smaller than 4*delta, where delta is the
  156. accuracy in the longitude of the sun (given by the function
  157. `solar-ecliptic-coordinates') in degrees since (delta/360) x (86400/60) = 4 x
  158. delta.  At present, delta = 0.01 degrees, so the value of the variable
  159. `solar-error' should be at least 0.04 minutes (about 2.5 seconds).")
  160.  
  161. (defvar solar-n-hemi-seasons
  162.   '("Vernal Equinox" "Summer Solstice" "Autumnal Equinox" "Winter Solstice")
  163.   "List of season changes for the northern hemisphere.")
  164.  
  165. (defvar solar-s-hemi-seasons
  166.   '("Autumnal Equinox" "Winter Solstice" "Vernal Equinox" "Summer Solstice")
  167.   "List of season changes for the southern hemisphere.")
  168.  
  169. (defvar solar-sidereal-time-greenwich-midnight 
  170.    nil 
  171.    "Sidereal time at Greenwich at midnight (universal time).")
  172.  
  173. (defvar solar-spring-or-summer-season nil  
  174.   "T if spring or summer and nil otherwise.
  175. Needed for polar areas, in order to know whether the day lasts 0 or 24 hours.")
  176.  
  177. (defun solar-setup ()
  178.   "Prompt user for latitude, longitude, and time zone."
  179.   (beep)
  180.   (if (not calendar-longitude)
  181.       (setq calendar-longitude
  182.             (solar-get-number
  183.              "Enter longitude (decimal fraction; + east, - west): ")))
  184.   (if (not calendar-latitude)
  185.       (setq calendar-latitude
  186.             (solar-get-number
  187.              "Enter latitude (decimal fraction; + north, - south): ")))
  188.   (if (not calendar-time-zone)
  189.       (setq calendar-time-zone
  190.             (solar-get-number
  191.              "Enter difference from Coordinated Universal Time (in minutes): "))))
  192.  
  193. (defun solar-get-number (prompt)
  194.   "Return a number from the minibuffer, prompting with PROMPT.
  195. Returns nil if nothing was entered."
  196.   (let ((x (read-string prompt "")))
  197.     (if (not (string-equal x ""))
  198.         (string-to-int x))))
  199.  
  200. ;; The condition-case stuff is needed to catch bogus arithmetic
  201. ;; exceptions that occur on some machines (like Sparcs)
  202. (defun solar-sin-degrees (x)
  203.   (condition-case nil
  204.       (sin (degrees-to-radians (mod x 360.0)))
  205.     (solar-sin-degrees x)))
  206. (defun solar-cosine-de